#include "mpWin32Func.h"
#include "mpLocaleUtils.h"

#if defined(PLATFORM_WINDOWS)

namespace MP{
namespace Win32Func{

//private member
namespace{

bool _getAccountSid(LPTSTR accountName, PSID *sid){
    PSID pSID = NULL;
    DWORD cbSid = 0;
    LPTSTR DomainName = NULL;
    DWORD cbDomainName = 0;
    SID_NAME_USE SIDNameUse;
    BOOL  bDone = FALSE;

    try
    {
        if(!LookupAccountNameW(NULL,
                               accountName,
                               pSID,
                               &cbSid,
                               DomainName,
                               &cbDomainName,
                               &SIDNameUse))
        {
            pSID = (PSID)malloc(cbSid);
            DomainName = (LPTSTR)malloc(cbDomainName * sizeof(TCHAR));
            if(!pSID || !DomainName)
            {
                throw;
            }
            if(!LookupAccountNameW(NULL,
                                   accountName,
                                   pSID,
                                   &cbSid,
                                   DomainName,
                                   &cbDomainName,
                                   &SIDNameUse))
            {
                throw;
            }
            bDone = TRUE;
        }
    }
    catch(...)
    {
        //nothing
    }

    if(DomainName)
    {
        free(DomainName);
    }

    if(!bDone && pSID)
    {
        free(pSID);
    }
    if(bDone)
    {
        *sid = pSID;
    }

    return bDone;
}

} //private member



//获取当前登录用户的TOKEN
bool mpsGetCurrentLogonUserToken(HANDLE & hToken){
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;

    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hProcessSnap)
        return false;

    pe32.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hProcessSnap, &pe32)){
        CloseHandle(hProcessSnap);
        return false;
    }

    bool result = false;
    do
    {
        if (_wcsicmp(pe32.szExeFile, L"explorer.exe") == 0)
        {
            HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);

            if (NULL == hProcess){
            }
            else{
                if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken)){
                    result = true;
                }
                CloseHandle( hProcess );
            }

            break;
        }
    } while (Process32Next(hProcessSnap, &pe32));

    CloseHandle(hProcessSnap);

    return result;
}

//获取运行程序的用户Local目录
bool mpsGetDefaultUserLocalPath(std::wstring & localPath){
    // Get path for each computer, non-user specific and non-roaming data.
    //CSIDL_APPDATA
    //CSIDL_LOCAL_APPDATA
    //CSIDL_COMMON_APPDATA
    wchar_t szPath[MAX_PATH] = { 0 };
    if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, szPath)))
    {
        localPath = szPath;
        memset(szPath, 0, sizeof(szPath));
        return true;
    }
    return false;
}

//获取运行程序的用户桌面目录
bool mpsGetDefaultUserDestopPath(std::wstring & destopPath){

    wchar_t szPath[MAX_PATH] = { 0 };
    if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, szPath)))
    {
        destopPath = szPath;
        memset(szPath, 0, sizeof(szPath));
        return true;
    }
    return false;
}

//获取所有用户的公共目录
bool mpsGetDefaultAllUserLocalPath(std::wstring & localPath){
    // Get path for each computer, non-user specific and non-roaming data.
    //CSIDL_APPDATA
    //CSIDL_LOCAL_APPDATA
    //CSIDL_COMMON_APPDATA

    wchar_t szPath[MAX_PATH] = { 0 };
    if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath)))
    {
        localPath = szPath;
        memset(szPath, 0, sizeof(szPath));

#if MAPLE_MODE_DEBUGGING
        localPath = L"D:";
#endif
        return true;
    }

    return false;
}

//获取当前登录用户的Local目录（针对以SYSTEM用户运行的SVR服务程序）
bool mpsGetCurrentLogonUserLocalPath(std::wstring & localPath){

    bool result = false;
    HANDLE hToken;

    if(mpsGetCurrentLogonUserToken(hToken)){
        // Get path for each computer, non-user specific and non-roaming data.
        //CSIDL_APPDATA
        //CSIDL_LOCAL_APPDATA
        //CSIDL_COMMON_APPDATA
        wchar_t szPath[MAX_PATH] = { 0 };
        if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, hToken, 0, szPath)))
        {
            localPath = szPath;
            memset(szPath, 0, sizeof(szPath));
            result = true;
        }
    }

    if (hToken != INVALID_HANDLE_VALUE)
        CloseHandle(hToken);
    return result;
}

//获取当前登录用户的Roaming目录（针对以SYSTEM用户运行的SVR服务程序）
bool mpsGetCurrentLogonUserRoamingPath(std::wstring & roamingPath){
    bool result = false;
    HANDLE hToken;

    if(mpsGetCurrentLogonUserToken(hToken)){
        // Get path for each computer, non-user specific and non-roaming data.
        //CSIDL_APPDATA
        //CSIDL_LOCAL_APPDATA
        //CSIDL_COMMON_APPDATA
        wchar_t szPath[MAX_PATH] = { 0 };
        if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, hToken, 0, szPath)))
        {
            roamingPath = szPath;
            memset(szPath, 0, sizeof(szPath));
            result = true;
        }
    }

    if (hToken != INVALID_HANDLE_VALUE)
        CloseHandle(hToken);
    return result;
}

//获取当前登录用户名称
bool mpsGetCurrentLogonUserName(std::wstring & userName){
    bool result = false;
    HANDLE hToken;

    if(mpsGetCurrentLogonUserToken(hToken)){

        if(ImpersonateLoggedOnUser(hToken)){
            wchar_t  infoBuf[1024] = { 0 };
            DWORD  bufCharCount = 1024;
            if(GetUserNameW(infoBuf, &bufCharCount) )
            {
                userName = infoBuf;
                result = true;
            }

            RevertToSelf();
        }
    }


    if (hToken != INVALID_HANDLE_VALUE)
        CloseHandle(hToken);

    return result;
}

//获取当前登录用户名称和SID
bool mpsGetCurrentLogonUserNameAndSid(std::wstring & userName, std::wstring & sid){

    bool result = false;
    HANDLE hToken;

    if(mpsGetCurrentLogonUserToken(hToken)){

        if(ImpersonateLoggedOnUser(hToken)){
            wchar_t infoBuf[1024] = { 0 };
            DWORD  bufCharCount = 1024;

            if(GetUserNameW(infoBuf, &bufCharCount))
            {
                userName = infoBuf;

                PSID pSid = NULL;

                if(_getAccountSid(infoBuf,&pSid)){
                    //从结构体中得到sid串
                    LPWSTR sidValue = NULL;
                    if(ConvertSidToStringSidW(pSid, &sidValue)){
                        sid = sidValue;

                        LocalFree(sidValue);
                        sidValue = NULL;

                        result = true;
                    }
                }
            }

            RevertToSelf();
        }
    }

    if (hToken != INVALID_HANDLE_VALUE)
         CloseHandle(hToken);

    return result;
}

}   //END Win32Func
}   //END MP







#endif // PLATFORM_WINDOWS
